Ext.define('Seq.grid.selection.Replicator', {
	override : 'Ext.grid.selection.Replicator',

	replicateSelection : function(ownerGrid, sel, extension) {

		// This can only handle extending rows
		if (extension.columns || sel.isColumns) {
			return;
		}

		var me = this, columns = me.columns, colCount, j, column, values, startIdx, endIdx, i, increment, store, record, prevValues, prevValue, selFirstRowIdx = sel
		        .getFirstRowIndex(), selLastRowIdx = sel.getLastRowIndex(), selectedRowCount = selLastRowIdx
		        - selFirstRowIdx + 1, lastTwoRecords = [], x, y;

		colCount = columns.length, store = columns[0].getView().dataSource;

		// Single row, just duplicate values into extension
		if (selectedRowCount === 1) {
			values = me.getColumnValues(sel.view.dataSource.getAt(selFirstRowIdx));
		}
		// Multiple rows, take the numeric values from the closest two rows, calculate an array of differences and
		// propagate it
		else {
			values = new Array(colCount);
			if (extension.rows < 0) {
				lastTwoRecords = [store.getAt(selFirstRowIdx + 1), store.getAt(selFirstRowIdx)];
			} else {
				lastTwoRecords = [store.getAt(selLastRowIdx - 1), store.getAt(selLastRowIdx)];
			}
			lastTwoRecords[0] = me.getColumnValues(lastTwoRecords[0]);
			lastTwoRecords[1] = me.getColumnValues(lastTwoRecords[1]);

			// The values array will be the differences between all numeric columns in the selection of the
			// closet two records.
			for (j = 0; j < colCount; j++) {
				x = lastTwoRecords[1][j];
				y = lastTwoRecords[0][j];
				if (!isNaN(x) && !isNaN(y)) {
					values[j] = Number(x) - Number(y);
				}
			}
		}

		// Loop from end to start of extension area
		if (extension.rows < 0) {
			startIdx = extension.end.rowIdx;
			endIdx = extension.start.rowIdx - 1;
			increment = -1;
		} else {
			startIdx = extension.start.rowIdx;
			endIdx = extension.end.rowIdx + 1;
			increment = 1;
		}

		// Replicate single selected row
		if (selectedRowCount === 1) {
			for (i = startIdx; i !== endIdx; i += increment) {
				record = store.getAt(i);
				for (j = 0; j < colCount; j++) {
					column = columns[j];
					if (column.dataIndex && !column.disableReplicator) {
						record.set(column.dataIndex, values[j]);
					}
				}
			}
		}
		// Add differences from closest two rows
		else {
			for (i = startIdx; i !== endIdx; i += increment) {
				record = store.getAt(i);
				prevValues = me.getColumnValues(store.getAt(i - increment));
				for (j = 0; j < colCount; j++) {
					column = columns[j];
					if (column.dataIndex && !column.disableReplicator) {
						prevValue = prevValues[j];
						if (!isNaN(prevValue)) {
							record.set(column.dataIndex, Ext.coerce(Number(prevValue) + values[j], prevValue));
						}
					}
				}
			}
		}
	}
});